/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package processor;

import javax.swing.JOptionPane;

/**
 * Class in using after checking the correction of grammar
 *
 * @author DYNG09
 */
public class SqlFormat {

    private String query;

    public SqlFormat() {
        this.query = null;
    }

    public SqlFormat(String q) {
        KeyWord kw = new KeyWord(q);
        this.query = kw.changKeyWordToLowerCase();
        this.query = this.replaceCharBreakLineBySpace(this.query, 0, this.query.length());
        this.query = this.changeSpacesToSingleSpace(this.query);
        this.query = this.deleteSpaceAtHeadAndTrailOperator(this.query);
    }

    public String format() {
        String fStr = "";
        DetectQuery dq = new DetectQuery(this.query);
        while (dq.getQuery().trim().length() != 0) {
            dq.getASingleQuery();
            int s = dq.detect();
            switch (s) {
                case Constant.SELECT_LV2:
                case Constant.SELECT:
                    fStr += selectFormat(dq.getSingleQuery()) + "\n";
                    break;
                case Constant.INSERT:
                    fStr += insertFormat(dq.getSingleQuery()) + "\n";
                    break;
                case Constant.UPDATE:
                    fStr += updateFormat(dq.getSingleQuery()) + "\n";
                    break;
                case Constant.DELETE:
                    fStr += deleteFormat(dq.getSingleQuery()) + "\n";
                    break;
                case Constant.ERROR:
                    JOptionPane.showMessageDialog(null, "Unknown error!");
                    return null;
            }
        }

        return fStr.trim();
    }

    private String selectFormat(String q) {
        String r = q;
        //break line between select..... | from......
        int fromPos;
        for (fromPos = 0; fromPos < r.length() - 4; fromPos++) {
            if (r.substring(fromPos, fromPos + 4).equals("from")) {
                break;
            }
        }
        int pos = fromPos - 1;
        while (r.charAt(pos) == ' ' || r.charAt(pos) == '\t') {
            r = eraseChar(r, pos);
            pos = pos - 1;
        }
        r = addChar(r, pos, '\n');
        //break line between from..... | where......
        int wherePos = -1;
        for (int i = 0; i < r.length() - 5; i++) {
            if (r.substring(i, i + 5).equals("where")) {
                wherePos = i;
                break;
            }
        }
        ////if existe where
        if (wherePos != -1) {
            pos = wherePos - 1;
            while (r.charAt(pos) == ' ' || r.charAt(pos) == '\t') {
                r = eraseChar(r, pos);
                pos = pos - 1;
            }
            r = addChar(r, pos, '\n');
        }

        return r;
    }

    public String insertFormat(String query) {
        String r = query;
        //group insert + into in a line
        for (int i = 0; i < r.length() - 3; i++) {
            if (r.substring(i, i + 4).equals("into")) {
                int pos = i - 1;
                while (r.charAt(pos) == ' ' || r.charAt(pos) == '\t') {
                    r = eraseChar(r, pos);
                    pos = pos - 1;
                }
                r = this.addChar(r, pos, ' ');
                break;
            }
        }
        //break line between insert into..... | values......
        int valuesPos;
        for (valuesPos = 0; valuesPos < r.length() - 6; valuesPos++) {
            if (r.substring(valuesPos, valuesPos + 6).equals("values")) {
                break;
            }
        }
        int pos = valuesPos - 1;
        while (r.charAt(pos) == ' ' || r.charAt(pos) == '\t') {
            r = eraseChar(r, pos);
            pos = pos - 1;
        }
        r = addChar(r, pos, '\n');

        return r;
    }

    public String updateFormat(String query) {
        String r = query;
        //break line between update..... | set......
        int setPos;
        for (setPos = 0; setPos < r.length() - 3; setPos++) {
            if (r.substring(setPos, setPos + 3).equals("set")) {
                break;
            }
        }
        int pos = setPos - 1;
        while (r.charAt(pos) == ' ' || r.charAt(pos) == '\t') {
            r = eraseChar(r, pos);
            pos = pos - 1;
        }
        r = addChar(r, pos, '\n');
        ////if existe where
        int wherePos = -1;
        for (int i = 0; i < r.length() - 5; i++) {
            if (r.substring(i, i + 5).equals("where")) {
                wherePos = i;
            }
        }
        if (wherePos != -1) {
            pos = wherePos - 1;
            while (r.charAt(pos) == ' ' || r.charAt(pos) == '\t') {
                r = eraseChar(r, pos);
                pos = pos - 1;
            }
            r = addChar(r, pos, '\n');
        }

        return r;
    }

    public String deleteFormat(String query) {
        String r = query;
        int pos;
        ////if existe where
        int wherePos = -1;
        for (int i = 0; i < r.length() - 5; i++) {
            if (r.substring(i, i + 5).equals("where")) {
                wherePos = i;
            }
        }
        if (wherePos != -1) {
            pos = wherePos - 1;
            while (r.charAt(pos) == ' ' || r.charAt(pos) == '\t') {
                r = eraseChar(r, pos);
                pos = pos - 1;
            }
            r = addChar(r, pos, '\n');
        }

        return r;
    }
    
    private String deleteSpaceAtHeadAndTrailOperator(String q){
        String r = q;
        for(int i = 1; i < r.length(); i++){
            char c = r.charAt(i);
            boolean flag = (c == '=' || c == '<' || c == '>');
            if(flag){
                int len = 1;
                c = r.charAt(i + 1);
                if(c == '=' || c == '>'){
                    len = 2;
                }
                CharSequence head = (r.charAt(i - 1) == ' ')? r.subSequence(0, i - 1) 
                                                        : r.subSequence(0, i);
                CharSequence trail = (r.charAt(i + len) == ' ')? r.substring(i + len + 1, r.length()) 
                                                        : r.substring(i + len, r.length());
                r = head + r.substring(i, i + len) + trail;
            }
        }
        
        return r;
    }

    private String replaceCharBreakLineBySpace(String q, int startPos, int endPos){
        int len = q.length();
        if(startPos < 0 || startPos > len || 
                endPos < 0 || endPos > len || 
                startPos > endPos)
            return null;
        String r = q.substring(startPos, endPos);
        r = r.replace('\n', ' ');
        
        return r;
    }
    
    private String changeSpacesToSingleSpace(String q){
        String r = q;
        for(int i = 0; i < r.length(); i++){
            if(r.charAt(i) == ' ' && r.charAt(i + 1) == ' '){
                r = this.eraseChar(r, i);
                i--;
            }
        }
        
        return r;
    }
    
    private String eraseChar(String q, int charAt) {
        return q.substring(0, charAt) + q.substring(charAt + 1, q.length());
    }

    private String addChar(String q, int afterCharAt, char c) {
        return q.substring(0, afterCharAt + 1) + c + q.substring(afterCharAt + 1, q.length());
    }

    /**
     * @return the query
     */
    public String getQuery() {
        return query;
    }

    /**
     * @param query the query to set
     */
    public void setQuery(String query) {
        KeyWord kw = new KeyWord(query);
        this.query = kw.changKeyWordToLowerCase();
        this.query = this.replaceCharBreakLineBySpace(this.query, 0, this.query.length());
        this.query = this.changeSpacesToSingleSpace(this.query);
    }
}
